package org.softmed.rest.server.test.report;

import java.awt.Desktop;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Date;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.hssf.util.Region;
import org.softmed.rest.server.test.scenario.TestCase;
import org.softmed.rest.server.test.scenario.TestScenario;
import org.softmed.rest.server.test.scenario.TestSuite;

public class XLSReportBuilder implements ReportBuilder {

	String titleString = "REST Server Administration Test";

	HSSFFont defaultBoldFont;

	HSSFFont defaultFont;
	HSSFFont title;
	HSSFFont scenario;
	HSSFFont redscenario;
	HSSFFont uri;
	HSSFFont regularGreen;
	HSSFFont regularBlack;
	HSSFFont regularRed;
	HSSFFont regularYellow;

	HSSFCellStyle defaultStyle;
	HSSFCellStyle defaultBoldStyle;
	HSSFCellStyle titleStyle;
	HSSFCellStyle scenarioStyle;
	HSSFCellStyle redscenarioStyle;
	HSSFCellStyle uriStyle;
	HSSFCellStyle redFontStyle;
	HSSFCellStyle blackStyle;
	HSSFCellStyle yellowStyle;

	HSSFCellStyle coloredBackground;
	HSSFCellStyle correct;
	HSSFCellStyle failed;

	HSSFSheet currentSheet;
	HSSFCellStyle redStyle;
	HSSFCellStyle greyStyle;
	HSSFCellStyle greenStyle;

	@Override
	public void createReport(TestSuite results) throws Throwable {
		String fileName = "rest-server-test-results-" + getDate() + ".xls";

		
		
		HSSFWorkbook wb = new HSSFWorkbook();
		setup(wb);

//		byte[] bytes = wb.getBytes();
//		bytes.length
		
		createSummary(wb, results);
		createDetailedReport(wb, results);

		FileOutputStream fileOut = new FileOutputStream(fileName);
		wb.write(fileOut);
		fileOut.close();

		File file = new File(fileName);
		Desktop.getDesktop().open(file);

	}

	private void createDetailedReport(HSSFWorkbook wb, TestSuite results) {
		currentSheet = wb.createSheet("Detailed Report");

		getTitleCell(1, 1).setCellValue(titleString);

		getTitleCell(1, 2).setCellValue(results.getTitle());

		if (results.getFailures() == 0) {
			getCell(1, 3).setCellValue(
					"PASSED " + "Tests:" + results.getTests() + " Passed:"
							+ results.getSucesses() + " Failed:"
							+ results.getFailures());

		} else {
			getRedCell(1, 2).setCellValue(
					"FAILED " + "Tests:" + results.getTests() + " Passed:"
							+ results.getSucesses() + " Failed:"
							+ results.getFailures());

		}

		List<TestScenario> scenarios = results.getScenarios();
		int y = 5;
		for (TestScenario testScenario : scenarios) {
			createDetailed(testScenario, y);
			y += 3 + testScenario.getTests();
		}
	}

	private void createDetailed(TestScenario testScenario, int y) {

		createScenarioHeaderDetail(testScenario, y);
		int ty = y + 1;

		List<TestCase> cases = testScenario.getCases();
		ty++;
		for (TestCase testCase : cases) {
			createDetailedReport(testCase, ty);
			ty++;
		}
		createColoredLine(ty, 20);

	}

	private void createScenarioHeaderDetail(TestScenario testScenario, int y) {
		int ty = y + 1;
		if (testScenario.getFailures() == 0) {

			getScenarioCell(1, y).setCellValue(testScenario.getTitle());

			getCell(1, ty).setCellValue(
					"PASSED " + "Tests:" + testScenario.getTests() + " Passed:"
							+ testScenario.getSucesses() + " Failed:"
							+ testScenario.getFailures());

		} else {

			getRedScenarioCell(1, y).setCellValue(testScenario.getTitle());

			getRedCell(1, ty).setCellValue(
					"FAILED " + "Tests:" + testScenario.getTests() + " Passed:"
							+ testScenario.getSucesses() + " Failed:"
							+ testScenario.getFailures());

		}

		getBoldCell(2, ty).setCellValue("Sucess");

		currentSheet.addMergedRegion(new Region(y, (short) 3, y, (short) 5));
		getBoldCell(3, y).setCellValue("Request");
		getBoldCell(3, ty).setCellValue("HttpMethod");
		getBoldCell(4, ty).setCellValue("MimeType");
		getBoldCell(5, ty).setCellValue("Body");

		currentSheet.addMergedRegion(new Region(y, (short) 6, y, (short) 8));
		getBoldCell(6, y).setCellValue("Response");
		getBoldCell(6, ty).setCellValue("Status");
		getBoldCell(7, ty).setCellValue("MimeType");
		getBoldCell(8, ty).setCellValue("Body");

	}

	private void createDetailedReport(TestCase testCase, int y) {
		if (testCase.isSucess()) {
			getURICell(1, y).setCellValue(testCase.getUri());

			getGreenCell(2, y).setCellValue(testCase.isSucess());

			// request values
			getCell(3, y).setCellValue(testCase.getRequest().getHttpMethod());
			getCell(4, y).setCellValue(testCase.getRequest().getMimeType());
			getWrapCell(5, y).setCellValue(
					new HSSFRichTextString(testCase.getRequest().getBody()));

			// response values
			getCell(6, y).setCellValue(testCase.getResponse().getStatus());
			getCell(7, y).setCellValue(testCase.getResponse().getMimeType());
			if (testCase.getResponse().getMimeType() != null
					&& !testCase.getResponse().getMimeType().equalsIgnoreCase(
							"text/html"))
				getWrapCell(8, y)
						.setCellValue(
								new HSSFRichTextString(testCase.getResponse()
										.getBody()));

		} else {
			getURICell(1, y).setCellValue(testCase.getUri());

			getRedCell(2, y).setCellValue(testCase.isSucess());

			// request values
			getRedCell(3, y)
					.setCellValue(testCase.getRequest().getHttpMethod());
			getRedCell(4, y).setCellValue(testCase.getRequest().getMimeType());
			getRedCell(5, y).setCellValue(
					new HSSFRichTextString(testCase.getRequest().getBody()));

			// response values
			getRedCell(6, y).setCellValue(testCase.getResponse().getStatus());
			getRedCell(7, y).setCellValue(testCase.getResponse().getMimeType());
			if (testCase.getResponse().getMimeType() != null
					&& !testCase.getResponse().getMimeType().equalsIgnoreCase(
							"text/html"))
				getRedCell(8, y)
						.setCellValue(
								new HSSFRichTextString(testCase.getResponse()
										.getBody()));
			// getRedCell(8, y).setCellValue(new HSSFRichTextString());
		}

		currentSheet.autoSizeColumn((short) 1);
		currentSheet.autoSizeColumn((short) 2);
		currentSheet.autoSizeColumn((short) 3);
		currentSheet.autoSizeColumn((short) 4);
		currentSheet.autoSizeColumn((short) 5);
		currentSheet.autoSizeColumn((short) 6);
		currentSheet.autoSizeColumn((short) 7);
		currentSheet.autoSizeColumn((short) 8);

	}

	private void createSummary(HSSFWorkbook wb, TestSuite results) {
		currentSheet = wb.createSheet("Summary");

		getTitleCell(1, 1).setCellValue(titleString);
		getTitleCell(1, 2).setCellValue(results.getTitle());

		if (results.getFailures() == 0)
			getTitleCell(7, 1).setCellValue("OK");
		else
			getTitleCell(7, 1).setCellValue("Fail");

		int ty = 3;
		getCell(1, ty).setCellValue("Tests");
		getCell(2, ty).setCellValue(results.getTests());

		getCell(4, ty).setCellValue("Passed");
		getCell(5, ty).setCellValue(results.getSucesses());

		getCell(7, ty).setCellValue("Failed");
		getCell(8, ty).setCellValue(results.getFailures());

		List<TestScenario> scenarios = results.getScenarios();
		int y = 6;
		for (TestScenario testScenario : scenarios) {
			createSummary(testScenario, y);
			y += 3;
		}

	}

	private void createSummary(TestScenario testScenario, int y) {
		int ty = createScenarioHeader(testScenario, y);

		createColoredLine(ty + 1, 20);

	}

	private int createScenarioHeader(TestScenario testScenario, int y) {
		int ty = 0;
		if (testScenario.getFailures() == 0) {

			getScenarioCell(1, y).setCellValue(testScenario.getTitle());
			getScenarioCell(7, y).setCellValue("PASSED");

			ty = y + 1;
			getCell(1, ty).setCellValue("Tests");
			getCell(2, ty).setCellValue(testScenario.getTests());

			getCell(4, ty).setCellValue("Passed");
			getCell(5, ty).setCellValue(testScenario.getSucesses());

			getCell(7, ty).setCellValue("Failed");
			getCell(8, ty).setCellValue(testScenario.getFailures());

		} else {
			getRedScenarioCell(1, y).setCellValue(testScenario.getTitle());
			getRedScenarioCell(7, y).setCellValue("FAILED");

			ty = y + 1;
			getRedCell(1, ty).setCellValue("Tests");
			getRedCell(2, ty).setCellValue(testScenario.getTests());

			getRedCell(4, ty).setCellValue("Passed");
			getRedCell(5, ty).setCellValue(testScenario.getSucesses());

			getRedCell(7, ty).setCellValue("Failed");
			getRedCell(8, ty).setCellValue(testScenario.getFailures());
		}
		return ty;
	}

	public void createColoredLine(int y, int width) {

		HSSFCell cell = null;
		for (int i = 0; i < width; i++) {
			cell = getCell(i, y);
			cell.setCellStyle(greyStyle);
		}
	}

	public void setup(HSSFWorkbook wb) {

		// RED background
		redStyle = wb.createCellStyle();
		redStyle.setFillForegroundColor(HSSFColor.RED.index);
		redStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);

		// GREY BACKGROUND
		greyStyle = wb.createCellStyle();
		greyStyle.setFillForegroundColor(HSSFColor.GREY_50_PERCENT.index);
		greyStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);

		// TITLE
		title = wb.createFont();
		title.setFontHeightInPoints((short) 16);
		title.setFontName("Arial");
		// title.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);

		// Fonts are set into a style so create a new one to use.
		titleStyle = wb.createCellStyle();
		titleStyle.setFont(title);
		titleStyle.setAlignment(defaultStyle.ALIGN_LEFT);
		titleStyle.setVerticalAlignment(defaultStyle.VERTICAL_TOP);

		// SCENARIO
		scenario = wb.createFont();
		scenario.setFontHeightInPoints((short) 14);
		scenario.setFontName("Arial");
		// scenario.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		scenario.setItalic(true);

		// Fonts are set into a style so create a new one to use.
		scenarioStyle = wb.createCellStyle();
		scenarioStyle.setFont(scenario);
		scenarioStyle.setAlignment(defaultStyle.ALIGN_LEFT);
		scenarioStyle.setVerticalAlignment(defaultStyle.VERTICAL_TOP);

		// RED SCENARIO
		redscenario = wb.createFont();
		redscenario.setFontHeightInPoints((short) 14);
		redscenario.setFontName("Arial");
		// redscenario.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		redscenario.setItalic(true);
		redscenario.setColor(HSSFColor.RED.index);

		// Fonts are set into a style so create a new one to use.
		redscenarioStyle = wb.createCellStyle();
		redscenarioStyle.setFont(redscenario);
		redscenarioStyle.setAlignment(defaultStyle.ALIGN_LEFT);
		redscenarioStyle.setVerticalAlignment(defaultStyle.VERTICAL_TOP);

		// URI
		uri = wb.createFont();
		uri.setFontHeightInPoints((short) 10);
		uri.setFontName("Courier New");
		uri.setColor(HSSFColor.BLUE_GREY.index);

		// Fonts are set into a style so create a new one to use.
		uriStyle = wb.createCellStyle();
		uriStyle.setFont(uri);
		uriStyle.setAlignment(defaultStyle.ALIGN_LEFT);
		uriStyle.setVerticalAlignment(defaultStyle.VERTICAL_TOP);

		// regular red
		regularRed = wb.createFont();
		regularRed.setFontHeightInPoints((short) 10);
		regularRed.setFontName("Arial");
		regularRed.setColor(HSSFColor.RED.index);

		// Fonts are set into a style so create a new one to use.
		redFontStyle = wb.createCellStyle();
		redFontStyle.setFont(regularRed);
		redFontStyle.setWrapText(true);
		redFontStyle.setAlignment(defaultStyle.ALIGN_LEFT);
		redFontStyle.setVerticalAlignment(defaultStyle.VERTICAL_TOP);

		// regular yellow
		regularYellow = wb.createFont();
		regularYellow.setFontHeightInPoints((short) 10);
		regularYellow.setFontName("Arial");
		regularYellow.setColor(HSSFColor.YELLOW.index);

		// Fonts are set into a style so create a new one to use.
		yellowStyle = wb.createCellStyle();
		yellowStyle.setFont(regularYellow);
		yellowStyle.setAlignment(defaultStyle.ALIGN_LEFT);
		yellowStyle.setVerticalAlignment(defaultStyle.VERTICAL_TOP);

		// regular green
		regularGreen = wb.createFont();
		regularGreen.setFontHeightInPoints((short) 10);
		regularGreen.setFontName("Arial");
		regularGreen.setColor(HSSFColor.GREEN.index);

		// Fonts are set into a style so create a new one to use.
		greenStyle = wb.createCellStyle();
		greenStyle.setFont(regularGreen);
		greenStyle.setAlignment(defaultStyle.ALIGN_LEFT);
		greenStyle.setVerticalAlignment(defaultStyle.VERTICAL_TOP);

		// regular red
		regularBlack = wb.createFont();
		regularBlack.setFontHeightInPoints((short) 10);
		regularBlack.setFontName("Arial");
		regularBlack.setColor(HSSFColor.BLACK.index);

		// Fonts are set into a style so create a new one to use.
		blackStyle = wb.createCellStyle();
		blackStyle.setFont(regularBlack);
		blackStyle.setWrapText(true);
		blackStyle.setAlignment(defaultStyle.ALIGN_LEFT);
		blackStyle.setVerticalAlignment(defaultStyle.VERTICAL_TOP);

		// default
		defaultFont = wb.createFont();
		defaultFont.setFontHeightInPoints((short) 10);
		defaultFont.setFontName("Arial");
		defaultFont.setColor(HSSFColor.BLACK.index);

		// Fonts are set into a style so create a new one to use.
		defaultStyle = wb.createCellStyle();
		defaultStyle.setFont(defaultFont);
		defaultStyle.setWrapText(false);
		defaultStyle.setAlignment(defaultStyle.ALIGN_LEFT);
		defaultStyle.setVerticalAlignment(defaultStyle.VERTICAL_TOP);

		// default
		defaultBoldFont = wb.createFont();
		defaultBoldFont.setFontHeightInPoints((short) 10);
		defaultBoldFont.setFontName("Arial");
		defaultBoldFont.setColor(HSSFColor.BLACK.index);
		defaultBoldFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		// Fonts are set into a style so create a new one to use.
		defaultBoldStyle = wb.createCellStyle();
		defaultBoldStyle.setFont(defaultBoldFont);
		defaultBoldStyle.setWrapText(false);
		defaultBoldStyle.setAlignment(defaultStyle.ALIGN_LEFT);
		defaultBoldStyle.setVerticalAlignment(defaultStyle.VERTICAL_TOP);

	}

	public HSSFCell getBoldCell(int x, int y) {
		HSSFCell cell = getCell(x, y);
		cell.setCellStyle(defaultBoldStyle);
		return cell;

	}

	public HSSFCell getWrapCell(int x, int y) {
		HSSFCell cell = getCell(x, y);
		cell.setCellStyle(blackStyle);
		return cell;

	}

	public HSSFCell getTitleCell(int x, int y) {
		HSSFCell cell = getCell(x, y);
		cell.setCellStyle(titleStyle);
		return cell;

	}

	public HSSFCell getScenarioCell(int x, int y) {
		HSSFCell cell = getCell(x, y);
		cell.setCellStyle(scenarioStyle);
		return cell;

	}

	public HSSFCell getRedScenarioCell(int x, int y) {
		HSSFCell cell = getCell(x, y);
		cell.setCellStyle(redscenarioStyle);
		return cell;

	}

	public HSSFCell getURICell(int x, int y) {
		HSSFCell cell = getCell(x, y);
		cell.setCellStyle(uriStyle);
		return cell;
	}

	public HSSFCell getRedCell(int x, int y) {
		HSSFCell cell = getCell(x, y);
		cell.setCellStyle(redFontStyle);
		return cell;
	}

	public HSSFCell getGreenCell(int x, int y) {
		HSSFCell cell = getCell(x, y);
		cell.setCellStyle(greenStyle);
		return cell;
	}

	public HSSFCell getYellowCell(int x, int y) {
		HSSFCell cell = getCell(x, y);
		cell.setCellStyle(yellowStyle);
		return cell;
	}

	public HSSFCell getCell(int x, int y) {
		HSSFRow row = currentSheet.getRow(y);
		if (row == null)
			row = currentSheet.createRow(y);

		HSSFCell cell = row.getCell((short) x);
		if (cell == null)
			cell = row.createCell((short) x);

		cell.setCellStyle(defaultStyle);

		return cell;
	}

	public String getDate() {
		Date date = new Date();
		return date.getDate() + "-" + date.getMonth() + "-"
				+ (date.getYear() + 1900) + "-" + date.getHours() + "h"
				+ date.getMinutes() + "m" + date.getSeconds() + "s";
	}

}
